<?php
###########################################################################
#  Copyright (C) 2006-2007 Glyphix, Inc. <briz@glyphix.com>               #
#                                                                         #
#  Permission is hereby granted, free of charge, to any person obtaining  #
#  a copy of this software and associated documentation files (the        #
#  "Software"), to deal in the Software without restriction, including    #
#  without limitation the rights to use, copy, modify, merge, publish,    #
#  distribute, sublicense, and/or sell copies of the Software, and to     #
#  permit persons to whom the Software is furnished to do so, subject to  #
#  the following conditions:                                              #
#                                                                         #
#  The above copyright notice and this permission notice shall be         #
#  included in all copies or substantial portions of the Software.        #
#                                                                         #
#  Except as contained in this notice, the name(s) of the above           #
#  copyright holders shall not be used in advertising or otherwise to     #
#  promote the sale, use or other dealings in this Software without       #
#  prior written authorization.                                           #
#                                                                         #
#  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,        #
#  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF     #
#  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. #
#  IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR      #
#  OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,  #
#  ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR  #
#  OTHER DEALINGS IN THE SOFTWARE.                                        #
###########################################################################

/**
 * GXGoogleDrive
 *
 * Functions to work with Google Drive.
 * @author		Brad Brizendine <briz@glyphix.com>
 * @link		http://www.glyphix.com/
 * @license		http://opensource.org/licenses/bsd-license.php BSD License
 * @version		1.0
 * @package		GXPage
 * @subpackage	Modules
 * @copyright	Copyright 2006 - 2007, Glyphix, Inc.
 * @uses		GXModule, curl
 */



/**************************
 * GOOGLE AUTH STEPS
 *
 * Register an app in https://console.developers.google.com/
 * Enable the Drive API in APIs & Auth
 * In Credentials, create a "Client ID for web application" (for standard OAuth2 authorization of users).
 * In Credentials, create a "Service Account" to allow a server to impersonate a different account (required for below).
 *
 * Allow access for particular apps from within the google apps for domains console.
 * https://admin.google.com/domain.tld
 * Security -> Advanced Settings -> Manage API Client Access
 **************************/


set_include_path(realpath(__DIR__ .'/Library/php-google-spreadsheet-client-master/src/') . PATH_SEPARATOR . get_include_path());

function google_spreadsheet_client_autoload($class){
    if(strpos($class, '\\') !== false) {
        include str_replace("\\", "/", $class) . '.php';
    }
}
spl_autoload_register('google_spreadsheet_client_autoload');

use Google\Spreadsheet\DefaultServiceRequest;
use Google\Spreadsheet\ServiceRequestFactory;

// this uses the "impersonate a user" method: https://developers.google.com/api-client-library/php/auth/service-accounts#authorizingrequests

// and then we integrate this: https://github.com/asimlqt/php-google-spreadsheet-client

class GXGoogleSpreadsheet extends GXModule {

	private $GClient = null;
	private $gtoken = null;

	private $client_email = null;
	private $user_to_impersonate = null;

	private $sheet = null;	// the Google\Spreadsheet\Worksheet object

	// so far, only used for spreadsheet key, but will probably work for other doc types
	private $doc = null;

	// init GXGoogleAuth
	public function __construct( $config = null ){
		parent::__construct($config);

		// store the key and type as defined in the config
		$this->doc = (object)array(
			'key'=>$this->getval($config, 'key'),			// the key of the spreadsheet
			'type'=>$this->getatt($config, 'key', 'type'),	// the type of the key (sheet, of course)
			'ws'=>$this->getatt($config, 'key', 'ws')		// the position of the worksheet (zero-based)
			);

		// grab all the credential settings
		$this->client_email = $this->getval($config, 'client_email');
		$this->user_to_impersonate = $this->getval($config, 'user_to_impersonate');

		// read in the p12 file
		$p12_path = realpath($this->GXPage->Layout->Server->Config .'/' .$this->getval($config, 'p12'));
		$p12 = file_get_contents($p12_path);

		// Specify the service account's email address and private key, and the scopes that you want to access
		// If you have delegated domain-wide access to the service account and you want to impersonate a user account, specify the email address of the user account when you create the Google_Auth_AssertionCredentials object
		try{
			$credentials = new Google_Auth_AssertionCredentials(
				$this->client_email,
				array('https://spreadsheets.google.com/feeds'),
				$p12,
				'notasecret',                                 // Default P12 password
				'http://oauth.net/grant_type/jwt/1.0/bearer', // Default grant type
				$this->user_to_impersonate
			);
		}catch(Google_Exception $e){
			$msg = 'Unable to obtain credentials [' .print_r($e, true) .']';
			trigger_error($msg, E_USER_ERROR);
			return false;
		}

		// change the tmp dir to avoid permissions issues
		$gconf = new Google_Config();
		$gconf->setClassConfig("Google_Cache_File", "directory", dirname(__FILE__) .'/tmp');

		// Create a Google_Client object and use it to acquire an access token
		try{
			$this->GClient = new Google_Client($gconf);
			$this->GClient->setApplicationName($this->getval($config, 'application_name'));
			$this->GClient->setClientId($this->getval($config, 'client_id'));
			$this->GClient->setAssertionCredentials($credentials);
			if($this->GClient->getAuth()->isAccessTokenExpired()){
				$this->GClient->getAuth()->refreshTokenWithAssertion();
			}
		}catch(Google_Exception $e){
			$msg = 'Unable to initialize Google_Client [' .print_r($e, true) .']';
			trigger_error($msg, E_USER_ERROR);
			return false;
		}

		// muck about with the token...the php-google-spreadsheet-client project can't deal with the full return from google client
		$tk = $this->GClient->getAccessToken();
		$objtk = json_decode($tk);
		$this->gtoken = $objtk->access_token;

		if( ! $this->gtoken){
			$msg = 'Unable to obtain authorization token [' .print_r($this->gtoken, true) .']';
			trigger_error($msg, E_USER_ERROR);
			return false;
		}

		// all our caller wants to know is if we made it here
		return true;
	}

	/**
	 * get
	 *
	 * Get the spreadsheet referenced by the config in system.xml
	 * @returns Google\Spreadsheet\Worksheet
	 */
	public function get($key = null, $ws = 0){
		if( ! $key) $key = $this->doc->key;
		if( ! is_scalar($ws)) $ws = $this->doc->ws;

		// prime the code
		try{
			$request = new DefaultServiceRequest($this->gtoken);
			ServiceRequestFactory::setInstance($request);
		}catch(Exception $e){
			$msg = 'Unable to instantiate spreadsheet service [' .print_r($e, true) .']';
			trigger_error($msg, E_USER_ERROR);
			return false;
		}

		// get the spreadsheet service
		$service = new Google\Spreadsheet\SpreadsheetService();

		// grab by id
		try{
			$doc = $service->getSpreadsheetById($key);
			$sheetList = $doc->getWorksheets();
			$sheet = $sheetList[$ws];
		}catch(Exception $e){
			$msg = 'Unable to obtain referenced spreadsheet by key[' .$key .']...error=' .print_r($e, true);
			trigger_error($msg, E_USER_ERROR);
			return false;
		}

		// store a reference
		$this->sheet = $sheet;

		// return the sheet
		return $this->sheet;
	}

	public function getListData($format = GXDOM::AS_GXDOM, $nodeName = 'List', $itemName = 'Item'){
		if( ! $this->sheet){
			$this->get();
		}

		// get the list feed xml doc so we can add a row
		$list = $this->sheet->getListFeed();

		// grab the entries (which returns an array of ListFeed objects)
		$entries = $list->getEntries();

		// return the format we want
		$r = null;

		switch($format){

			case GXDOM::AS_GXDOM:
				$r = new GXDOM($nodeName);
				foreach($entries as $row){
					$r->{$itemName}($row->getValues());
				}
				break;

			case 'array':
				$r = array();
				foreach($entries as $row){
					$r[] = $row->getValues();
				}
				break;

			default:
				$r = $entries;

		}

		// return our new gxdom object
		return $r;
	}

	public function truncateData(){
		if( ! $this->sheet){
			$this->get();
		}

		// have to build the payload ourselves, since php-google-spreadsheet-client doesn't allow access to the returned xml
		$entry[] = '<entry xmlns="http://www.w3.org/2005/Atom" xmlns:gs="http://schemas.google.com/spreadsheets/2006">';
			$entry[] = '<id>' .$this->sheet->getId() .'</id>';
			$entry[] = '<title type="text">' .$this->sheet->getTitle() .'</title>';
			$entry[] = '<gs:colCount>' .$this->sheet->getColCount() .'</gs:colCount>';
			$entry[] = '<gs:rowCount>1</gs:rowCount>';
		$entry[] = '</entry>';

		// here's the xml payload
		$xml = implode('', $entry);


/*
		<entry>
  <id>
    https://spreadsheets.google.com/feeds/worksheets/key/private/full/worksheetId
  </id>
  <updated>2007-07-30T18:51:30.666Z</updated>
  <category scheme="http://schemas.google.com/spreadsheets/2006"
    term="http://schemas.google.com/spreadsheets/2006#worksheet"/>
  <title type="text">Income</title>
  <content type="text">Expenses</content>
  <link rel="http://schemas.google.com/spreadsheets/2006#listfeed"
    type="application/atom+xml" href="https://spreadsheets.google.com/feeds/list/key/worksheetId/private/full"/>
  <link rel="http://schemas.google.com/spreadsheets/2006#cellsfeed"
    type="application/atom+xml" href="https://spreadsheets.google.com/feeds/cells/key/worksheetId/private/full"/>
  <link rel="self" type="application/atom+xml"
    href="https://spreadsheets.google.com/feeds/worksheets/key/private/full/worksheetId"/>
  <link rel="edit" type="application/atom+xml"
    href="https://spreadsheets.google.com/feeds/worksheets/key/private/full/worksheetId/version"/>
  <gs:rowCount>45</gs:rowCount>
  <gs:colCount>15</gs:colCount>
</entry>
*/




        $foo = ServiceRequestFactory::getInstance()->put($this->sheet->getEditUrl(), $xml);

        return true;
	}

}
